from xml.dom.minidom import parseString
import xml.dom

#-----------------------------------------------------------------------
class XMLNode:
    """
    XMLNode -- generic class for holding an XML node

    XMLNode.elementName: the tag of this node
    XMLNode.elementText: the text content of this node
    XMLNode.attrib: the properties of this node
    XMLNode.name1: the list of child nodes of name1

    ################################
    xmlStr = \"\"\"<xml foo="32">
    <name bar="10">Name0</name>
    <name bar="11" baz="12">Name1</name>
    </xml>\"\"\"

    f = XMLNode.parseXML(xmlStr)

    #print f.elementName              # xml
    #print f['foo']                   # 32
    #print f.name                     # [<name XMLNode>, <name XMLNode>]
    #print f.name[0].elementName      # name
    #print f.name[0]["bar"]           # 10
    #print f.name[0].elementText      # Name0
    #print f.name[1].elementName      # name
    #print f.name[1]["bar"]           # 11
    #print f.name[1]["baz"]           # 12

    """

    def __init__(self):
        """Construct an empty XML node."""
        self.elementName=""
        self.elementText=""
        self.attrib={}
        self.xml=""

    def __setitem__(self, key, item):
        """Store a node's attribute in the attrib hash."""
        #print "__setitem__,",key,item
        self.attrib[key] = item

    def __getitem__(self, key):
        """Retrieve a node's attribute from the attrib hash."""
        #print "__getitem__,",key
        return self.attrib[key]
    
    def __str__(self):
        str = ""
        str += "elementName:%s\n"%self.elementName
        str += "elementText:%s\n"%self.elementText
        str += "attrib:%s\n"%self.attrib
        return str
    #-----------------------------------------------------------------------
    @classmethod
    def parseXML(cls, xmlStr, storeXML=True):
        """Convert an XML string into a nice instance tree of XMLNodes.

        xmlStr -- the XML to parse
        storeXML -- if True, stores the XML string in the root XMLNode.xml
        """
        #print "parseXML,",xmlStr,storeXML

        def __parseXMLElement(element, thisNode):
            """Recursive call to process this XMLNode."""
            thisNode.elementName = element.nodeName

            ##print element.nodeName

            # add element attributes as attributes to this node
            for i in range(element.attributes.length):
                an = element.attributes.item(i)
                thisNode[an.name] = an.nodeValue

            for a in element.childNodes:
                if a.nodeType == xml.dom.Node.ELEMENT_NODE:

                    child = XMLNode()
                    try:
                        list = getattr(thisNode, a.nodeName)
                    except AttributeError:
                        setattr(thisNode, a.nodeName, [])

                    # add the child node as an attrib to this node
                    list = getattr(thisNode, a.nodeName);
                    ##print "appending child: %s to %s" % (a.nodeName, thisNode.elementName)
                    list.append(child);

                    __parseXMLElement(a, child)

                elif a.nodeType == xml.dom.Node.TEXT_NODE:
                    thisNode.elementText += a.nodeValue

            return thisNode
        
        dom = parseString(xmlStr)

        # get the root
        rootNode = XMLNode()
        if storeXML: 
            rootNode.xml = xmlStr

        return __parseXMLElement(dom.firstChild, rootNode)

